package com.loto.insurance.mis.web.service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import com.loto.insurance.framework.InsFactory;
import com.loto.insurance.framework.MsgStatusEnum;
import com.loto.insurance.framework.Air.InsAir;
import com.loto.insurance.framework.Air.InsReturnMsg;
import com.loto.insurance.framework.Air.OrderItemInfo;
import com.loto.insurance.mis.web.db.mapper.CustFeeFlowMapper;
import com.loto.insurance.mis.web.db.mapper.OrderFlowMapper;
import com.loto.insurance.mis.web.db.mapper.OrderInfoMapper;
import com.loto.insurance.mis.web.db.mapper.CustInfoMapper;
import com.loto.insurance.mis.web.db.mapper.PolicyFlowMapper;
import com.loto.insurance.mis.web.db.mapper.PolicyInfoAirMapper;
import com.loto.insurance.mis.web.db.mapper.PolicyInfoMapper;
import com.loto.insurance.mis.web.db.mapper.PolicyInfoTravelMapper;
import com.loto.insurance.mis.web.entity.CustFeeFlow;
import com.loto.insurance.mis.web.entity.CustInfo;
import com.loto.insurance.mis.web.entity.OrderFlow;
import com.loto.insurance.mis.web.entity.OrderInfo;
import com.loto.insurance.mis.web.entity.PolicyFlow;
import com.loto.insurance.mis.web.entity.PolicyInfo;
import com.loto.insurance.mis.web.entity.PolicyInfoAir;
import com.loto.insurance.mis.web.entity.PolicyInfoTravel;
import com.loto.insurance.mis.web.entity.service.PaidPolicy;
import com.loto.insurance.mis.web.entity.service.SimplePolicyInfo;
import com.loto.insurance.mis.web.enumeration.FeeTypeEnum;
import com.loto.insurance.mis.web.enumeration.InsTypeEnum;
import com.loto.insurance.mis.web.enumeration.OrderStatusEnum;
import com.loto.insurance.mis.web.enumeration.PayChannelEnum;
import com.loto.insurance.mis.web.enumeration.PayForEnum;
import com.loto.insurance.mis.web.enumeration.PaymentStatusEnum;
import com.loto.insurance.mis.web.enumeration.PolicyFeeStatusEnum;
import com.loto.insurance.mis.web.enumeration.PolicyStatusEnum;
import com.loto.utils.DateUtils;

@Service
public class PayService {
  @Autowired
  CustFeeFlowMapper custFeeFlowMapper;

  @Autowired
  OrderInfoMapper orderInfoMapper;

  @Autowired
  CustInfoMapper custInfoMapper;

  @Autowired
  OrderFlowMapper orderFlowMapper;

  @Autowired
  PolicyInfoAirMapper policyInfoAirMapper;

  @Autowired
  PolicyFlowMapper policyFlowMapper;

  @Autowired
  PolicyInfoTravelMapper policyInfoTravelMapper;

  @Autowired
  PolicyInfoMapper policyInfoMapper;

  @Autowired
  DataSourceTransactionManager transactionManager;

  @Autowired
  private DefaultTransactionDefinition def;

  public String doPay(
	  com.loto.insurance.mis.web.entity.service.CustFeeInit feeInit, long custId) {
	UUID uuid = UUID.randomUUID();
	String uid = uuid.toString().replace("-", "");

	// 判断交易号是否已存在
	if (custFeeFlowMapper.findFlowByPayNo(feeInit.getInitPayNo()).size() == 0) {
	  if (feeInit.getInitFor() == PayForEnum.ORDER.getIndex()) {
		// 判断该ID是否已支付
		OrderInfo orderInfo = orderInfoMapper.findOrderPayInfoBySubId(feeInit
		    .getInitRelatedFid());
		CustInfo custInfo = custInfoMapper.findUsefulfeeById(custId);
		BigDecimal fee = feeInit.getInitChangeFee();
		BigDecimal usefulFee = custInfo.getCustUsefulFee();
		if (orderInfo != null) { // 若未支付，添加FLOW，修改订单状态，发起投保动作
		  long orderId = orderInfo.getOrderId();

		  TransactionStatus status = transactionManager.getTransaction(def);
		  try {
			// (1)添加FEE_FLOW
			CustFeeFlow consumeFeeFlow = new CustFeeFlow();
			if (!feeInit.getInitChannel().equals(
			    PayChannelEnum.BALANCE.getName())) {// 第三方支付
			  // 一笔充值
			  CustFeeFlow feeFlow = new CustFeeFlow();
			  feeFlow.setFlowChangedFee(fee);
			  feeFlow.setFlowChannel(feeInit.getInitChannel());
			  feeFlow.setFlowPaidOn(feeInit.getInitCreditedOn());
			  feeFlow.setFlowCustFid(custId);
			  feeFlow.setFlowSubCustFid(feeInit.getInitCustFid());
			  feeFlow.setFlowFlag(PaymentStatusEnum.SUC.getIndex());
			  feeFlow.setFlowFor(feeInit.getInitFor());
			  feeFlow.setFlowRelatedFid(orderId);
			  feeFlow.setFlowMemo(feeInit.getInitOutPayDesc());
			  feeFlow.setFlowOutPayNo(feeInit.getInitOutPayNo());
			  feeFlow.setFlowPayNo(feeInit.getInitPayNo());
			  feeFlow.setFlowType(FeeTypeEnum.SUPPLEMENT.getIndex());
			  feeFlow.setFlowOutPayDesc(feeInit.getInitOutPayDesc());
			  feeFlow.setFlowOutPayNo(feeInit.getInitOutPayNo());
			  feeFlow.setFlowPayFee(feeInit.getInitPayFee());
			  feeFlow.setFlowPlatformId(uid);
			  feeFlow.setFlowRoyaltyFee(feeInit.getInitRoyaltyFee());
			  feeFlow.setFlowRoyaltyMemo(feeInit.getInitRoyaltyMemo());
			  feeFlow.setFlowRoyaltyPayee(feeInit.getInitRoyaltyPayee());
			  feeFlow.setFlowRoyaltyPayer(feeInit.getInitRoyaltyPayer());
			  custFeeFlowMapper.insertCustFeeFlow(feeFlow);

			  // 一笔消费
			  consumeFeeFlow.setFlowChangedFee(fee.subtract(fee
				  .multiply(new BigDecimal(2))));
			  consumeFeeFlow.setFlowChannel(feeInit.getInitChannel());
			  consumeFeeFlow.setFlowPaidOn(feeInit.getInitCreditedOn());
			  consumeFeeFlow.setFlowCustFid(custId);
			  consumeFeeFlow.setFlowSubCustFid(feeInit.getInitCustFid());
			  consumeFeeFlow.setFlowFlag(PaymentStatusEnum.SUC.getIndex());
			  consumeFeeFlow.setFlowFor(feeInit.getInitFor());
			  consumeFeeFlow.setFlowRelatedFid(orderId);
			  consumeFeeFlow.setFlowMemo(feeInit.getInitOutPayDesc());
			  consumeFeeFlow.setFlowOutPayNo(feeInit.getInitOutPayNo());
			  consumeFeeFlow.setFlowPayNo(feeInit.getInitPayNo());
			  consumeFeeFlow.setFlowType(FeeTypeEnum.CONSUME.getIndex());
			  consumeFeeFlow.setFlowOutPayDesc(feeInit.getInitOutPayDesc());
			  consumeFeeFlow.setFlowOutPayNo(feeInit.getInitOutPayNo());
			  consumeFeeFlow.setFlowPayFee(feeInit.getInitPayFee().subtract(
				  feeInit.getInitPayFee().multiply(new BigDecimal(2))));
			  consumeFeeFlow.setFlowPlatformId(uid);
			  consumeFeeFlow.setFlowRoyaltyFee(feeInit.getInitRoyaltyFee());
			  consumeFeeFlow.setFlowRoyaltyMemo(feeInit.getInitRoyaltyMemo());
			  consumeFeeFlow.setFlowRoyaltyPayee(feeInit.getInitRoyaltyPayee());
			  consumeFeeFlow.setFlowRoyaltyPayer(feeInit.getInitRoyaltyPayer());
			} else if (usefulFee.compareTo(orderInfo.getOrderSettleAmount()) > -1) {// 余额支付
			  // 一笔消费
			  consumeFeeFlow.setFlowChangedFee(fee.subtract(fee
				  .multiply(new BigDecimal(2))));
			  consumeFeeFlow.setFlowChannel(feeInit.getInitChannel());
			  consumeFeeFlow.setFlowPaidOn(feeInit.getInitCreditedOn());
			  consumeFeeFlow.setFlowCustFid(custId);
			  consumeFeeFlow.setFlowSubCustFid(feeInit.getInitCustFid());
			  consumeFeeFlow.setFlowFlag(PaymentStatusEnum.SUC.getIndex());
			  consumeFeeFlow.setFlowFor(feeInit.getInitFor());
			  consumeFeeFlow.setFlowRelatedFid(orderId);
			  consumeFeeFlow.setFlowMemo(feeInit.getInitOutPayDesc());
			  consumeFeeFlow.setFlowOutPayNo(feeInit.getInitOutPayNo());
			  consumeFeeFlow.setFlowPayNo(feeInit.getInitPayNo());
			  consumeFeeFlow.setFlowType(FeeTypeEnum.CONSUME.getIndex());
			  consumeFeeFlow.setFlowOutPayDesc(feeInit.getInitOutPayDesc());
			  consumeFeeFlow.setFlowOutPayNo(feeInit.getInitOutPayNo());
			  consumeFeeFlow.setFlowPayFee(feeInit.getInitPayFee());
			  consumeFeeFlow.setFlowPlatformId(uid);
			  consumeFeeFlow.setFlowRoyaltyFee(feeInit.getInitRoyaltyFee());
			  consumeFeeFlow.setFlowRoyaltyMemo(feeInit.getInitRoyaltyMemo());
			  consumeFeeFlow.setFlowRoyaltyPayee(feeInit.getInitRoyaltyPayee());
			  consumeFeeFlow.setFlowRoyaltyPayer(feeInit.getInitRoyaltyPayer());

			  // 如有分润，则增加分润流
			  if (feeInit.getInitRoyaltyFee().compareTo(new BigDecimal(0)) > 0) {
				CustFeeFlow royaltyFeeFlow = new CustFeeFlow();
				royaltyFeeFlow.setFlowChangedFee(feeInit.getInitRoyaltyFee());
				royaltyFeeFlow.setFlowChannel(feeInit.getInitChannel());
				royaltyFeeFlow.setFlowPaidOn(DateUtils.addMinute(
				    feeInit.getInitCreditedOn(), 1));
				royaltyFeeFlow.setFlowCustFid(custId);
				royaltyFeeFlow.setFlowSubCustFid(feeInit.getInitCustFid());
				royaltyFeeFlow.setFlowFlag(PaymentStatusEnum.SUC.getIndex());
				royaltyFeeFlow.setFlowFor(feeInit.getInitFor());
				royaltyFeeFlow.setFlowRelatedFid(orderId);
				royaltyFeeFlow.setFlowMemo(feeInit.getInitOutPayDesc());
				royaltyFeeFlow.setFlowOutPayNo(feeInit.getInitOutPayNo());
				royaltyFeeFlow.setFlowPayNo(feeInit.getInitPayNo());
				royaltyFeeFlow.setFlowType(FeeTypeEnum.ROYALTY.getIndex());
				royaltyFeeFlow.setFlowOutPayDesc(feeInit.getInitOutPayDesc());
				royaltyFeeFlow.setFlowOutPayNo(feeInit.getInitOutPayNo());
				royaltyFeeFlow.setFlowPayFee(feeInit.getInitRoyaltyFee());
				royaltyFeeFlow.setFlowPlatformId(uid);
				royaltyFeeFlow.setFlowRoyaltyFee(new BigDecimal(0));
				royaltyFeeFlow.setFlowRoyaltyMemo(feeInit.getInitRoyaltyMemo());
				royaltyFeeFlow.setFlowRoyaltyPayee(feeInit
				    .getInitRoyaltyPayee());
				royaltyFeeFlow.setFlowRoyaltyPayer(feeInit
				    .getInitRoyaltyPayer());
				custFeeFlowMapper.insertCustFeeFlow(royaltyFeeFlow);
			  }

			  // 修改余额
			  Map<String, Object> params = new HashMap<String, Object>();
			  params.put("custId", custId);
			  params.put(
				  "changedFee",
				  orderInfo.getOrderSettleAmount().subtract(
				      orderInfo.getOrderSettleAmount().multiply(
				          new BigDecimal(2))));
			  custInfoMapper.updateUsefulfeeById(params);
			} else {
			  transactionManager.rollback(status);
			  return null;
			}
			long flowId = custFeeFlowMapper.insertCustFeeFlow(consumeFeeFlow);
			if (flowId <= 0) {
			  transactionManager.rollback(status);
			  return null;
			}
			// (2)修改订单状态为支付成功
			Map<String, Object> params = new HashMap<String, Object>();
			params.put("orderId", orderId);
			params.put("orderStatusFid", OrderStatusEnum.PAID.getIndex());
			params.put("orderPaidOn", feeInit.getInitCreditedOn());
			orderInfoMapper.updateOrderStatusById(params);

			// (3)创建订单流
			OrderFlow orderFlow = new OrderFlow();
			orderFlow.setFlowOrderFid(orderId);
			orderFlow.setFlowOperFid(0);
			orderFlow.setFlowOrderStatusFid(OrderStatusEnum.PAID.getIndex());
			orderFlow.setFlowOrderStatus(OrderStatusEnum.PAID.getName());
			orderFlow.setFlowMemo(OrderStatusEnum.PAID.getDesc());
			orderFlowMapper.insertOrderFlow(orderFlow);
			// (4)修改保单状态和费用状态为支付成功
			params = new HashMap<String, Object>();
			params.put("orderId", orderId);
			params.put("feeStatusId", PolicyFeeStatusEnum.PAID.getIndex());

			Map<String, Object> statusParams = new HashMap<String, Object>();
			statusParams.put("orderId", orderId);
			statusParams.put("statusId", PolicyStatusEnum.PAID.getIndex());

			Map<String, Object> policyParams = new HashMap<String, Object>();
			policyParams.put("orderId", orderId);
			policyParams.put("flowInsTypeFid",
			    orderInfo.getOrderProductTypeFid());
			policyParams.put("flowPolicyStatusFid",
			    PolicyStatusEnum.PAID.getIndex());
			policyParams.put("flowPolicyStatus",
			    PolicyStatusEnum.PAID.getName());
			policyParams.put("flowFeeFlowFid", flowId);
			policyParams.put("flowMemo", PolicyStatusEnum.PAID.getDesc());
			if (orderInfo.getOrderProductTypeFid() == InsTypeEnum.AIR
			    .getIndex()) {
			  policyInfoAirMapper.updatePolicyFeeStatusByOrderId(params);
			  policyInfoAirMapper.updatePolicyStatusByOrderId(statusParams);
			  // (5)批量创建保单流
			  policyFlowMapper.insertAirPolicyFlowBat(policyParams);
			} else if (orderInfo.getOrderProductTypeFid() == InsTypeEnum.TRAVEL
			    .getIndex()) {
			  policyInfoTravelMapper.updatePolicyFeeStatusByOrderId(params);
			  policyInfoTravelMapper.updatePolicyStatusByOrderId(statusParams);
			  // (5)批量创建保单流
			  policyFlowMapper.insertTravelPolicyFlowBat(policyParams);
			}
			transactionManager.commit(status);

		  } catch (Exception ex) {
			ex.printStackTrace();
			transactionManager.rollback(status);
			uid = null;
		  }

		} else if (!feeInit.getInitChannel().equals(
		    PayChannelEnum.BALANCE.getName())) { // 若已支付，按充值计
		  TransactionStatus status = transactionManager.getTransaction(def);
		  try {
			// 添加FEE_FLOW
			CustFeeFlow feeFlow = new CustFeeFlow();
			feeFlow.setFlowChangedFee(fee);
			feeFlow.setFlowChannel(feeInit.getInitChannel());
			feeFlow.setFlowPaidOn(feeInit.getInitCreditedOn());
			feeFlow.setFlowCustFid(feeInit.getInitCustFid());
			feeFlow.setFlowFlag(PaymentStatusEnum.SUC.getIndex());
			feeFlow.setFlowFor(feeInit.getInitFor());
			feeFlow.setFlowMemo(feeInit.getInitMemo());
			feeFlow.setFlowOutPayNo(feeInit.getInitOutPayNo());
			feeFlow.setFlowPayNo(feeInit.getInitPayNo());
			feeFlow.setFlowRelatedFid(0);
			feeFlow.setFlowType(FeeTypeEnum.SUPPLEMENT.getIndex());
			feeFlow.setFlowOutPayDesc(feeInit.getInitOutPayDesc());
			feeFlow.setFlowOutPayNo(feeInit.getInitOutPayNo());
			feeFlow.setFlowPayFee(feeInit.getInitPayFee());
			feeFlow.setFlowPlatformId(uid);
			feeFlow.setFlowRoyaltyFee(feeInit.getInitRoyaltyFee());
			feeFlow.setFlowRoyaltyMemo(feeInit.getInitRoyaltyMemo());
			feeFlow.setFlowRoyaltyPayee(feeInit.getInitRoyaltyPayee());
			feeFlow.setFlowRoyaltyPayer(feeInit.getInitRoyaltyPayer());
			custFeeFlowMapper.insertCustFeeFlow(feeFlow);
			// 修改余额
			Map<String, Object> params = new HashMap<String, Object>();
			params.put("custId", custId);
			params.put("changedFee", fee);
			custInfoMapper.updateUsefulfeeById(params);

			transactionManager.commit(status);
		  } catch (Exception ex) {
			ex.printStackTrace();
			transactionManager.rollback(status);
			uid = null;
		  }
		}
	  } else if (feeInit.getInitFor() == PayForEnum.INVOICE.getIndex()) {

	  }
	}
	return uid;
  }

  // 投保
  public List<PaidPolicy> doApproval(String platId) {
	List<PaidPolicy> paidPolicyList = new ArrayList<PaidPolicy>();
	OrderInfo orderInfo = orderInfoMapper.findPaidOrderByFeeFlowPlatId(platId);
	if (orderInfo != null) {
	  long orderId = orderInfo.getOrderId();
	  if (orderInfo.getOrderProductTypeFid() == InsTypeEnum.AIR.getIndex()) {
		paidPolicyList = doAirApproval(orderInfo,
		    orderInfo.getOrderPlatformId());
	  } else if (orderInfo.getOrderProductTypeFid() == InsTypeEnum.TRAVEL
		  .getIndex()) {
		paidPolicyList = doTravelApproval(orderInfo,
		    orderInfo.getOrderPlatformId());
	  }
	  TransactionStatus status = transactionManager.getTransaction(def);
	  try {
		// 更新订单信息
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("orderId", orderId);
		params.put("orderStatusFid", OrderStatusEnum.INSURED_SUC.getIndex());
		orderInfoMapper.updateOrderStatusById(params);

		// 增加订单流
		OrderFlow orderFlow = new OrderFlow();
		orderFlow.setFlowOrderFid(orderId);
		orderFlow.setFlowOperFid(0);
		orderFlow.setFlowOrderStatusFid(OrderStatusEnum.INSURED_SUC.getIndex());
		orderFlow.setFlowOrderStatus(OrderStatusEnum.INSURED_SUC.getName());
		orderFlow.setFlowMemo(OrderStatusEnum.INSURED_SUC.getDesc());
		orderFlowMapper.insertOrderFlow(orderFlow);

		transactionManager.commit(status);
	  } catch (Exception ex) {
		ex.printStackTrace();
		transactionManager.rollback(status);
	  }
	}
	return paidPolicyList;
  }

  private List<PaidPolicy> doAirApproval(OrderInfo orderInfo, String platId) {
	List<PaidPolicy> paidPolicyList = new ArrayList<PaidPolicy>();
	long orderId = orderInfo.getOrderId();
	InsAir ins = InsFactory.GenerateInsAirProcessor(orderInfo.getProductEx(),
	    orderInfo.getProductCode());
	OrderItemInfo info = null;
	PaidPolicy paidPolicy = null;
	List<PolicyInfoAir> policyList = policyInfoAirMapper
	    .findPolicyInfoByPlatId(platId);
	if (policyList != null) {
	  for (PolicyInfoAir p : policyList) {
		info = new OrderItemInfo();
		info.setFlightNo(p.getPolicyFlightNo());
		info.setFromPeriod(p.getPolicyBegin());
		info.setHolderBirth(p.getPolicyHolderBirth());
		info.setHolderCredentialNo(p.getPolicyHolderCredentialNo());
		info.setHolderCredentialType(p.getPolicyHolderCredentialType());
		info.setHolderGender(p.getPolicyHolderGender());
		info.setHolderName(p.getPolicyHolderName());
		info.setTransOrderNo(p.getPolicyOutOrderNo());
		info.setInsuredBirth(p.getPolicyInsuredBirth());
		info.setInsuredCredentialNo(p.getPolicyInsuredCredentialNo());
		info.setInsuredCredentialType(p.getPolicyInsuredCredentialType());
		info.setInsuredEmail(p.getPolicyInsuredEmail());
		info.setInsuredGender(p.getPolicyInsuredGender());
		info.setInsuredName(p.getPolicyInsuredName());
		info.setInsuredTel(p.getPolicyInsuredTel());
		InsReturnMsg msg = ins.PolicyApproval(info);
		paidPolicy = new PaidPolicy();
		paidPolicy.setPolicyOutOrderNo(p.getPolicyOutOrderNo());
		TransactionStatus status = transactionManager.getTransaction(def);
		try {
		  // 更新保单信息
		  Map<String, Object> params = new HashMap<String, Object>();
		  params = new HashMap<String, Object>();
		  params.put("policyOutOrderNo", p.getPolicyOutOrderNo());
		  params.put("orderId", orderId);

		  PolicyStatusEnum statusEnum = PolicyStatusEnum.INSURED_FAILS;
		  if (msg.getStatus() == MsgStatusEnum.SUCCESS
			  && !msg.getInsNo().isEmpty()) { // 投保成功
			params.put("statusId", PolicyStatusEnum.INSURED_SUC);
			params.put("policyTradeOrderNo", msg.getInsTransNo());
			params.put("policyNo", msg.getInsNo());
			policyInfoAirMapper.updatePolicyByOutOrderNoOrderId(params);
			statusEnum = PolicyStatusEnum.INSURED_SUC;
		  } else {
			params.put("statusId", PolicyStatusEnum.INSURED_FAILS);
			policyInfoAirMapper.updatePolicyStatusByOutOrderNoOrderId(params);
			paidPolicy.setMsg(msg.getMessage());
		  }
		  params = new HashMap<String, Object>();
		  params.put("policyOutOrderNo", p.getPolicyOutOrderNo());
		  params.put("orderId", orderId);
		  PolicyInfoAir pInfo = policyInfoAirMapper
			  .findPolicyInfoByOutOrderNoOrderId(params);
		  // 创建保单流
		  PolicyFlow policyFlow = new PolicyFlow();
		  policyFlow.setFlowInsTypeFid(InsTypeEnum.AIR.getIndex());
		  policyFlow.setFlowPolicyFid(pInfo.getPolicyId());
		  policyFlow.setFlowOperFid(0);
		  policyFlow.setFlowPolicyStatusFid(statusEnum.getIndex());
		  policyFlow.setFlowPolicyStatus(statusEnum.getName());
		  policyFlow.setFlowMemo(msg.getMessage());
		  policyFlowMapper.insertPolicyFlow(policyFlow);

		  transactionManager.commit(status);

		  paidPolicy.setInsNo(msg.getInsNo());
		  paidPolicy.setPolicyTradeOrderNo(msg.getInsTransNo());
		} catch (Exception ex) {
		  ex.printStackTrace();
		  transactionManager.rollback(status);
		}
		paidPolicyList.add(paidPolicy);
	  }
	}
	return paidPolicyList;
  }

  private List<PaidPolicy> doTravelApproval(OrderInfo orderInfo, String platId) {
	List<PaidPolicy> paidPolicyList = new ArrayList<PaidPolicy>();
	long orderId = orderInfo.getOrderId();
	InsAir ins = InsFactory.GenerateInsAirProcessor(orderInfo.getProductEx(),
	    orderInfo.getProductCode());
	OrderItemInfo info = null;
	PaidPolicy paidPolicy = null;
	List<PolicyInfoTravel> policyList = policyInfoTravelMapper
	    .findPolicyInfoByPlatId(platId);
	if (policyList != null) {
	  for (PolicyInfoTravel p : policyList) {
		info = new OrderItemInfo();
		info.setFlightNo(p.getPolicyTravelLine());
		info.setFromPeriod(p.getPolicyBegin());
		info.setHolderBirth(p.getPolicyHolderBirth());
		info.setHolderCredentialNo(p.getPolicyHolderCredentialNo());
		info.setHolderCredentialType(p.getPolicyHolderCredentialType());
		info.setHolderGender(p.getPolicyHolderGender());
		info.setHolderName(p.getPolicyHolderName());
		info.setTransOrderNo(p.getPolicyOutOrderNo());
		info.setInsuredBirth(p.getPolicyInsuredBirth());
		info.setInsuredCredentialNo(p.getPolicyInsuredCredentialNo());
		info.setInsuredCredentialType(p.getPolicyInsuredCredentialType());
		info.setInsuredEmail(p.getPolicyInsuredEmail());
		info.setInsuredGender(p.getPolicyInsuredGender());
		info.setInsuredName(p.getPolicyInsuredName());
		info.setInsuredTel(p.getPolicyInsuredTel());
		InsReturnMsg msg = ins.PolicyApproval(info);
		paidPolicy = new PaidPolicy();
		paidPolicy.setPolicyOutOrderNo(p.getPolicyOutOrderNo());
		TransactionStatus status = transactionManager.getTransaction(def);
		try {
		  // 更新保单信息
		  Map<String, Object> params = new HashMap<String, Object>();
		  params = new HashMap<String, Object>();
		  params.put("statusId", PolicyStatusEnum.INSURED_SUC);
		  params.put("policyOutOrderNo", p.getPolicyOutOrderNo());
		  params.put("orderId", orderId);

		  PolicyStatusEnum statusEnum = PolicyStatusEnum.INSURED_FAILS;
		  if (msg.getStatus() == MsgStatusEnum.SUCCESS
			  && !msg.getInsNo().isEmpty()) { // 投保成功
			params.put("policyTradeOrderNo", msg.getInsTransNo());
			params.put("policyNo", msg.getInsNo());
			policyInfoTravelMapper.updatePolicyByOutOrderNoOrderId(params);
			statusEnum = PolicyStatusEnum.INSURED_SUC;
		  } else {
			policyInfoTravelMapper
			    .updatePolicyStatusByOutOrderNoOrderId(params);
		  }
		  params = new HashMap<String, Object>();
		  params.put("policyOutOrderNo", p.getPolicyOutOrderNo());
		  params.put("orderId", orderId);
		  PolicyInfoTravel pInfo = policyInfoTravelMapper
			  .findPolicyInfoByOutOrderNoOrderId(params);
		  // 创建保单流
		  PolicyFlow policyFlow = new PolicyFlow();
		  policyFlow.setFlowInsTypeFid(InsTypeEnum.TRAVEL.getIndex());
		  policyFlow.setFlowPolicyFid(pInfo.getPolicyId());
		  policyFlow.setFlowOperFid(0);
		  policyFlow.setFlowPolicyStatusFid(statusEnum.getIndex());
		  policyFlow.setFlowPolicyStatus(statusEnum.getName());
		  policyFlow.setFlowMemo(msg.getMessage());
		  policyFlowMapper.insertPolicyFlow(policyFlow);

		  transactionManager.commit(status);

		  paidPolicy.setInsNo(msg.getInsNo());
		  paidPolicy.setPolicyTradeOrderNo(msg.getInsTransNo());
		} catch (Exception ex) {
		  ex.printStackTrace();
		  transactionManager.rollback(status);
		}
		paidPolicyList.add(paidPolicy);
	  }
	}
	return paidPolicyList;
  }

  // 退保
  public String cancelPolicy(SimplePolicyInfo policyInfo, long custId) {
	UUID uuid = UUID.randomUUID();
	String uid = uuid.toString().replace("-", "");
	// 取得保单信息
	Map<String, Object> params = new HashMap<String, Object>();
	params.put("policyNo", policyInfo.getPolicyNo());
	params.put("custId", custId);
	params.put("policyOutOrderNo", policyInfo.getPolicyOutOrderNo());
	params.put("policyTradeOrderNo", policyInfo.getPolicyTradeOrderNo());
	PolicyInfo policy = policyInfoMapper.findCanCanceledPolicyByNo(params);
	// 获取余额
	CustInfo custInfo = custInfoMapper.findUsefulfeeById(custId);
	if (policy != null
	    && custInfo != null
	    && custInfo.getCustUsefulFee().compareTo(
	        policy.getPolicyRealAmount().subtract(
	            policy.getPolicySettleAmount())) >= 0) {
	  // 退
	  InsAir ins = InsFactory.GenerateInsAirProcessor(policy.getProductEx(),
		  policy.getProductCode());
	  OrderItemInfo cItemInfo = new OrderItemInfo();
	  cItemInfo.setInsuranceNo(policyInfo.getPolicyNo());
	  InsReturnMsg m = ins.PolicyCancel(cItemInfo);
	  // 修改保单状态、创建保单流、如成功则退款
	  PolicyStatusEnum pStatus = PolicyStatusEnum.SURRENDER_FAILS;
	  if (m.getStatus() == MsgStatusEnum.SUCCESS) {
		pStatus = PolicyStatusEnum.SURRENDER_SUC;
	  }
	  TransactionStatus status = transactionManager.getTransaction(def);

	  try {
		// 修改保单状态
		params = new HashMap<String, Object>();
		params.put("statusId", pStatus.getIndex());
		params.put("policyId", policy.getPolicyId());

		if (policy.getOrderProductTypeFid() == InsTypeEnum.AIR.getIndex()) {
		  policyInfoAirMapper.updatePolicyStatusById(params);
		} else if (policy.getOrderProductTypeFid() == InsTypeEnum.TRAVEL
		    .getIndex()) {
		  policyInfoTravelMapper.updatePolicyStatusById(params);
		}
		long feeFlowId = 0;
		// 退保成功则退款
		if (m.getStatus() == MsgStatusEnum.SUCCESS) {
		  // 修改保单费用状态
		  params = new HashMap<String, Object>();
		  params.put("feeStatusId", PolicyFeeStatusEnum.REFUND_SUC.getIndex());
		  params.put("policyId", policy.getPolicyId());

		  if (policy.getOrderProductTypeFid() == InsTypeEnum.AIR.getIndex()) {
			policyInfoAirMapper.updatePolicyFeeStatusById(params);
		  } else if (policy.getOrderProductTypeFid() == InsTypeEnum.TRAVEL
			  .getIndex()) {
			policyInfoTravelMapper.updatePolicyFeeStatusById(params);
		  }

		  // 退结算金额到帐户余额
		  Calendar now = Calendar.getInstance();
		  CustFeeFlow feeFlow = new CustFeeFlow();
		  feeFlow.setFlowChangedFee(policy.getPolicySettleAmount());
		  feeFlow.setFlowChannel(PayChannelEnum.BALANCE.getName());
		  feeFlow.setFlowPaidOn(now.getTime());
		  feeFlow.setFlowCustFid(custId);
		  feeFlow.setFlowSubCustFid(policyInfo.getPolicyCustFid());
		  feeFlow.setFlowFlag(PaymentStatusEnum.SUC.getIndex());

		  if (policy.getOrderProductTypeFid() == InsTypeEnum.AIR.getIndex()) {
			feeFlow.setFlowFor(PayForEnum.POLICY_AIR.getIndex());
		  } else if (policy.getOrderProductTypeFid() == InsTypeEnum.TRAVEL
			  .getIndex()) {
			feeFlow.setFlowFor(PayForEnum.POLICY_TRAVEL.getIndex());
		  }

		  feeFlow.setFlowRelatedFid(policy.getPolicyId());
		  feeFlow.setFlowMemo(policyInfo.getPolicyNo()
			  + FeeTypeEnum.REFUND.getName());
		  feeFlow.setFlowOutPayNo(policyInfo.getPolicyNo());
		  feeFlow.setFlowPayNo(policyInfo.getPolicyNo());
		  feeFlow.setFlowType(FeeTypeEnum.REFUND.getIndex());
		  feeFlow.setFlowOutPayDesc(policyInfo.getPolicyNo());
		  feeFlow.setFlowOutPayNo(policyInfo.getPolicyNo());
		  feeFlow.setFlowPayFee(policy.getPolicySettleAmount());
		  feeFlow.setFlowPlatformId(uid);
		  feeFlow.setFlowRoyaltyFee(new BigDecimal(0));
		  feeFlow.setFlowRoyaltyMemo("");
		  feeFlow.setFlowRoyaltyPayee("");
		  feeFlow.setFlowRoyaltyPayer("");
		  custFeeFlowMapper.insertCustFeeFlow(feeFlow);
		  feeFlowId = feeFlow.getFlowId();
		  params = new HashMap<String, Object>();
		  params.put("custId", custId);
		  params.put("changedFee", policy.getPolicySettleAmount());
		  custInfoMapper.updateUsefulfeeById(params);
		}
		// 创建保单流
		PolicyFlow policyFlow = new PolicyFlow();
		policyFlow.setFlowInsTypeFid(policy.getOrderProductTypeFid());
		policyFlow.setFlowMemo(m.getMessage());
		policyFlow.setFlowPolicyFid(policy.getPolicyId());
		policyFlow.setFlowPolicyStatus(pStatus.getName());
		policyFlow.setFlowPolicyStatusFid(pStatus.getIndex());
		policyFlow.setFlowFeeFlowFid(feeFlowId);
		policyFlowMapper.insertPolicyFlow(policyFlow);

		transactionManager.commit(status);
		return uid;
	  } catch (Exception ex) {
		ex.printStackTrace();
		transactionManager.rollback(status);
	  }
	}
	return null;
  }

  // 退款
  public String refundPolicy(SimplePolicyInfo policyInfo, long custId) {
	UUID uuid = UUID.randomUUID();
	String uid = uuid.toString().replace("-", "");
	// 取得保单信息
	Map<String, Object> params = new HashMap<String, Object>();
	params.put("subCustId", policyInfo.getPolicyCustFid());
	params.put("custId", custId);
	params.put("policyOutOrderNo", policyInfo.getPolicyOutOrderNo());
	PolicyInfo policy = policyInfoMapper.findCanRefundPolicyByOutNo(params);
	// 获取余额
	CustInfo custInfo = custInfoMapper.findUsefulfeeById(custId);
	if (policy != null
	    && custInfo != null
	    && custInfo.getCustUsefulFee().compareTo(
	        policy.getPolicyRealAmount().subtract(
	            policy.getPolicySettleAmount())) >= 0) {
	  TransactionStatus status = transactionManager.getTransaction(def);

	  try {
		// 修改保单费用状态
		params = new HashMap<String, Object>();
		params.put("feeStatusId", PolicyFeeStatusEnum.REFUND_SUC.getIndex());
		params.put("policyId", policy.getPolicyId());

		if (policy.getOrderProductTypeFid() == InsTypeEnum.AIR.getIndex()) {
		  policyInfoAirMapper.updatePolicyFeeStatusById(params);
		} else if (policy.getOrderProductTypeFid() == InsTypeEnum.TRAVEL
		    .getIndex()) {
		  policyInfoTravelMapper.updatePolicyFeeStatusById(params);
		}

		// 退结算金额到帐户余额
		Calendar now = Calendar.getInstance();
		CustFeeFlow feeFlow = new CustFeeFlow();
		feeFlow.setFlowChangedFee(policy.getPolicySettleAmount());
		feeFlow.setFlowChannel(PayChannelEnum.BALANCE.getName());
		feeFlow.setFlowPaidOn(now.getTime());
		feeFlow.setFlowCustFid(custId);
		feeFlow.setFlowSubCustFid(policyInfo.getPolicyCustFid());
		feeFlow.setFlowFlag(PaymentStatusEnum.SUC.getIndex());

		if (policy.getOrderProductTypeFid() == InsTypeEnum.AIR.getIndex()) {
		  feeFlow.setFlowFor(PayForEnum.POLICY_AIR.getIndex());
		} else if (policy.getOrderProductTypeFid() == InsTypeEnum.TRAVEL
		    .getIndex()) {
		  feeFlow.setFlowFor(PayForEnum.POLICY_TRAVEL.getIndex());
		}

		feeFlow.setFlowRelatedFid(policy.getPolicyId());
		feeFlow.setFlowMemo(policy.getPolicyInsuredName()
		    + policyInfo.getPolicyNo() + FeeTypeEnum.REFUND.getName());
		feeFlow.setFlowOutPayNo(policyInfo.getPolicyNo());
		feeFlow.setFlowPayNo(policyInfo.getPolicyNo());
		feeFlow.setFlowType(FeeTypeEnum.REFUND.getIndex());
		feeFlow.setFlowOutPayDesc(policyInfo.getPolicyNo());
		feeFlow.setFlowOutPayNo(policyInfo.getPolicyNo());
		feeFlow.setFlowPayFee(policy.getPolicySettleAmount());
		feeFlow.setFlowPlatformId(uid);
		feeFlow.setFlowRoyaltyFee(new BigDecimal(0));
		feeFlow.setFlowRoyaltyMemo("");
		feeFlow.setFlowRoyaltyPayee("");
		feeFlow.setFlowRoyaltyPayer("");
		custFeeFlowMapper.insertCustFeeFlow(feeFlow);

		params = new HashMap<String, Object>();
		params.put("custId", custId);
		params.put("changedFee", policy.getPolicySettleAmount());
		custInfoMapper.updateUsefulfeeById(params);

		transactionManager.commit(status);
		return uid;
	  } catch (Exception ex) {
		ex.printStackTrace();
		transactionManager.rollback(status);
	  }
	}
	return null;
  }

  // 取得余额
  public BigDecimal getUsefulFee(long custId) {
	CustInfo custInfo = custInfoMapper.findUsefulfeeById(custId);
	if (custInfo != null)
	  return custInfo.getCustUsefulFee();
	else
	  return new BigDecimal(0);
  }
}
